Skip to content

🎨 Palette: Add aria-pressed to toggle buttons - #156

Closed
alvin000009238 wants to merge 1 commit into
devfrom
palette-a11y-aria-pressed-4043510395242807888
Closed

🎨 Palette: Add aria-pressed to toggle buttons#156
alvin000009238 wants to merge 1 commit into
devfrom
palette-a11y-aria-pressed-4043510395242807888

Conversation

@alvin000009238

Copy link
Copy Markdown
Owner

💡 What: Added the aria-pressed attribute to the theme toggle and password visibility toggle buttons in both public/index.html and the dynamic JS files (frontend/theme.js and frontend/sync.js).
🎯 Why: Custom toggle buttons that rely solely on icon swaps or aria-label changes don't fully communicate their active/inactive state natively. aria-pressed makes their current state explicit.
📸 Before/After: N/A (no visual changes, attribute level)
♿ Accessibility: Screen readers will now announce the "pressed" state of the theme and password toggle buttons, significantly improving keyboard and screen reader accessibility and complying with ARIA guidelines for toggle buttons.


PR created automatically by Jules for task 4043510395242807888 started by @alvin000009238

Co-authored-by: alvin000009238 <107313913+alvin000009238@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings April 9, 2026 09:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves accessibility for custom toggle buttons by explicitly exposing their on/off state via aria-pressed, covering both the theme toggle and the password visibility toggle.

Changes:

  • Add aria-pressed to the theme toggle button (static HTML + dynamic updates in frontend/theme.js).
  • Add aria-pressed to the password visibility toggle button (static HTML + dynamic updates in frontend/sync.js).
  • Update referenced Vite-hashed /dist/ asset filenames in public/index.html and public/privacy.html.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
public/index.html Adds aria-pressed to toggle buttons and updates hashed CSS/JS asset references.
public/privacy.html Updates hashed CSS asset reference used by the privacy page.
frontend/theme.js Updates theme toggle’s aria-pressed whenever applyTheme() runs.
frontend/sync.js Updates password toggle’s aria-pressed in the click handler based on visibility state.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread public/privacy.html
href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Noto+Sans+TC:wght@400;500;700&display=swap"
rel="stylesheet">
<link rel="stylesheet" href="/dist/main-bt8E1vXG.css" id="vite-css">
<link rel="stylesheet" href="/dist/main-D2sAJccc.css" id="vite-css">

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public/privacy.html hardcodes a hashed /dist/main-*.css filename. Since the Docker image build only overwrites public/index.html from the frontend build stage (but not public/privacy.html), any change in the Vite output hash (e.g., due to VITE_COMMIT_HASH) can leave privacy.html pointing at a CSS file that doesn’t exist in public/dist, breaking styling for the privacy page. Consider either copying the post-build privacy.html from the frontend build stage into the final image, or commit an un-hashed placeholder href (e.g., /dist/main.css) and rely on scripts/inject-hash.js during build to rewrite it.

Copilot uses AI. Check for mistakes.
Comment thread public/index.html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit" async defer></script>
<script src="/theme-init.js"></script>
<link rel="stylesheet" href="/dist/main-bt8E1vXG.css" id="vite-css">
<link rel="stylesheet" href="/dist/main-D2sAJccc.css" id="vite-css">

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These /dist/main-*.css and /dist/main-*.js hash updates look unrelated to the stated purpose of adding aria-pressed. If this PR isn’t intended to include a full asset rebuild, consider reverting these hash-only changes (or updating the PR description) to avoid unnecessary merge conflicts/churn.

Copilot uses AI. Check for mistakes.
Comment thread public/index.html
Comment on lines 93 to +94
<button class="icon-btn theme-toggle-btn" id="themeToggleBtn" type="button" aria-label="切換至淺色模式"
title="切換主題">
title="切換主題" aria-pressed="false">

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aria-pressed is initialized to false in the static HTML, but the app’s default theme is dark (no data-theme unless grades-theme is 'light'). That means the initial ARIA state is incorrect for the default path until JS runs. Consider setting the initial aria-pressed to match the default rendered theme (and letting applyTheme() keep it in sync thereafter).

Copilot uses AI. Check for mistakes.
Comment thread frontend/theme.js
Comment on lines 27 to 32
if (toggleBtn) {
const nextThemeLabel = theme === 'light' ? '深色' : '淺色';
toggleBtn.setAttribute('aria-label', `切換至${nextThemeLabel}模式`);
toggleBtn.setAttribute('title', `切換至${nextThemeLabel}模式`);
toggleBtn.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
}

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applyTheme() now updates aria-pressed, but the existing unit tests for applyTheme() don’t assert this new behavior. Adding assertions for aria-pressed in tests/frontend/theme.test.js would help prevent regressions to this accessibility state.

Copilot uses AI. Check for mistakes.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates asset hashes and introduces aria-pressed attributes to theme and password visibility toggle buttons for improved accessibility. However, the review comments highlight that adding aria-pressed to buttons with dynamically changing labels (like "顯示密碼" / "隱藏密碼" or "切換至深色模式" / "切換至淺色模式") is not in line with WAI-ARIA best practices, as the label change itself is sufficient to convey the state and aria-pressed can lead to confusing screen reader announcements. The feedback suggests removing these aria-pressed attributes from both the JavaScript logic and the initial HTML markup.

Comment thread frontend/theme.js
const nextThemeLabel = theme === 'light' ? '深色' : '淺色';
toggleBtn.setAttribute('aria-label', `切換至${nextThemeLabel}模式`);
toggleBtn.setAttribute('title', `切換至${nextThemeLabel}模式`);
toggleBtn.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the WAI-ARIA Authoring Practices Guide (APG), a button that changes its label to reflect its state (e.g., "切換至深色模式" vs "切換至淺色模式") is not considered a toggle button and must not use the aria-pressed attribute. The label change itself is sufficient to communicate the state change. Adding aria-pressed to a button with a dynamic label can lead to confusing announcements in screen readers, such as "Switch to Light Mode, toggle button, pressed".

References
  1. According to WAI-ARIA guidelines, toggle buttons should not use aria-pressed if their label changes dynamically to reflect the state.

Comment thread frontend/sync.js
eyeOffIcon.style.display = 'block';
togglePasswordBtn.setAttribute('aria-label', '隱藏密碼');
togglePasswordBtn.setAttribute('title', '隱藏密碼');
togglePasswordBtn.setAttribute('aria-pressed', 'true');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the theme toggle, the password visibility button uses a dynamic label ("隱藏密碼" / "顯示密碼"). Per ARIA standards, aria-pressed should not be used on buttons whose labels change to reflect their state. It is recommended to remove the aria-pressed attribute to avoid redundant or confusing information for screen reader users.

References
  1. According to WAI-ARIA guidelines, toggle buttons should not use aria-pressed if their label changes dynamically to reflect the state.

Comment thread public/index.html
<div class="flex-center-gap-8 header-actions">
<button class="icon-btn theme-toggle-btn" id="themeToggleBtn" type="button" aria-label="切換至淺色模式"
title="切換主題">
title="切換主題" aria-pressed="false">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

As this button uses a dynamic label to communicate state changes, the aria-pressed attribute should be removed to comply with ARIA best practices for toggle buttons.

Suggested change
title="切換主題" aria-pressed="false">
title="切換主題">

Comment thread public/index.html
<label for="passwordInput">密碼</label>
<button type="button" id="togglePasswordBtn" class="toggle-password-btn"
aria-label="顯示密碼" title="顯示密碼">
aria-label="顯示密碼" title="顯示密碼" aria-pressed="false">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The aria-pressed attribute should be removed here as well, as the button's label is updated dynamically in the JavaScript logic to reflect the current state.

Suggested change
aria-label="顯示密碼" title="顯示密碼" aria-pressed="false">
aria-label="顯示密碼" title="顯示密碼">

@alvin000009238
alvin000009238 deleted the palette-a11y-aria-pressed-4043510395242807888 branch May 13, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants